// 1234567890abcdefghkl1234567890abcdefghkl


#include <string.h>
#include <stdio.h>
#include <stdlib.h>

typedef unsigned char uint8_t;

void print_byte(const uint8_t *bytes, size_t len)
{
	for(int i=0; i<len; i++){
		printf("%02x", bytes[i]);
		// printf("%c", bytes[i]);
	}
}

static int simple_buf_byte_find(const uint8_t *src, const uint8_t *sub, size_t src_len, size_t sub_len)
{
	const uint8_t *src_start = src;
	const uint8_t *src_last=src;
	const uint8_t *sub_start = sub;

	while(((sub - sub_start) < sub_len) && ((src - src_start) < src_len)) {
		if(*src == *sub){
			src++;
			sub++;
		}else{
			sub = sub_start;
			src = src_last+1;
			src_last = src;
		}
	}
	if((sub - sub_start) == sub_len){
		// find sub byte in src byte
		return ((src - src_start) - sub_len);
	}
	// not find sub byte in src byte
	return -1;
}

// #define BUF_MAX_LEN 4096
#define BUF_MAX_LEN 8

long file_find_bytes(FILE *ifs, long start_offset, const uint8_t *bytes, size_t byte_len)
{
	long cur_offset = start_offset;
	uint8_t data_buf[BUF_MAX_LEN];
	uint8_t *read_buf = data_buf;
	int res_buf_len = 0;
	int read_len = 0;
	int find_res = 0;
	fseek(ifs, start_offset, SEEK_SET);
	while((read_len = fread(read_buf+res_buf_len, 1, BUF_MAX_LEN-res_buf_len, ifs))) {
		find_res = simple_buf_byte_find(read_buf, bytes, read_len+res_buf_len, byte_len);
		if (find_res >= 0) {
			return (cur_offset + find_res - res_buf_len);
		}
		if(res_buf_len == 0) {
			res_buf_len = byte_len;
			memcpy(data_buf, data_buf+read_len-res_buf_len, res_buf_len); 
		}
		else{
			memcpy(data_buf, data_buf+read_len, res_buf_len); 	
		}
		cur_offset += read_len ;
	}
	return -1;
}

static long file_read_bytes(FILE *ifs, long start_offset, uint8_t *dest, size_t dest_len)
{
	fseek(ifs, start_offset, SEEK_SET);
	return fread(dest, 1, dest_len, ifs);
}

static int bytes_cmp(uint8_t *src, uint8_t *dest, size_t byte_len)
{
	for(int i=0; i<byte_len; i++) {
		if(src[i] != dest[i]) return 1;
	}
	return 0;
}

static int test(FILE *ifs, long start_offset, uint8_t *bytes, size_t byte_len, int can_find)
{
	long find_off = file_find_bytes(ifs, start_offset, bytes, byte_len);
	uint8_t buf[BUF_MAX_LEN];
	int exit_status = 0;
	if(find_off >= 0){
		file_read_bytes(ifs, find_off, buf, byte_len);
		if(bytes_cmp(bytes, buf, byte_len) != 0){
			printf("error: find bytes: ");
			print_byte(bytes, byte_len);
			printf(", off: %d, bytes: ", find_off);
			print_byte(buf, byte_len);
			printf("\n");
			exit_status = 1;
		}
	}else if(can_find){
		printf("byte not find: ");
		print_byte(bytes, byte_len);
		printf("\n");
		exit_status = 2;
	}
	return exit_status;
}

static void t_test()
{
	uint8_t org_data[12] = {2, 1, 0, 1};
	uint8_t sub_data[] = "9a";
	char *filename = "test.txt";
	FILE *ifs = fopen(filename, "r");
	for(int i=0; i<14; i++)
		test(ifs, i, sub_data, sizeof(sub_data)-1, i<8);

}

struct opt_key{
	uint8_t *mask;
	uint8_t *val;
	const char *org_val;
	struct opt_key *next;
}opt_key_t;


int main(int argc, char const *argv[])
{
	opt_key_t *header = NULL;
	if(argc < 2) {
		printf("usage: %s [r|w]")
	}

	t_test();
	return 0;
}